package cn.waka.sys.admin.service;

import static java.lang.System.out;

import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;

import cn.waka.sys.admin.dao.WechatConfigDao;
import cn.waka.sys.admin.object.WechatConfig;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.session.WxSessionManager;
import me.chanjar.weixin.mp.api.WxMpInMemoryConfigStorage;
import me.chanjar.weixin.mp.api.WxMpMessageHandler;
import me.chanjar.weixin.mp.api.WxMpMessageRouter;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutTextMessage;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

@Service
public class WechatConfigService {

	private static Logger log=LoggerFactory.getLogger(WechatConfigService.class);
	public void setDao(WechatConfigDao dao) {
		this.dao = dao;
	}

	@Autowired
	private WechatConfigDao dao;

	@Autowired
	private StringRedisTemplate redisTemplate;

	private OkHttpClient client = new OkHttpClient();

	private WxMpMessageRouter wxMpMessageRouter;
	private String accessToken;

	public WechatConfig findById(String appId) {
		return dao.findByAppId(appId);
	}

	public boolean saveConfig(String oldappid, WechatConfig config) {
		try {
			WechatConfig old = dao.find();

			if (old == null) {
				return dao.insertConfig(config.getAppId(), config.getName(), config.getAppSecret(), config.getToken(),
						config.getAesKey());
			} else {
				return dao.updateConfig(oldappid, config.getAppId(), config.getName(), config.getAppSecret(),
						config.getToken(), config.getAesKey());
			}
		} catch (Exception ex) {
			return false;
		}
	}

	public void replyMsg(HttpServletRequest request, HttpServletResponse response) {
		try {
			InputStream is = request.getInputStream();
			if (is != null && is.available() > 0) {
				WxMpXmlMessage inMessage = WxMpXmlMessage.fromXml(is);
				out.println("====event:" + inMessage.getEvent() + " key:" + inMessage.getEventKey());
				out.println("====post:" + inMessage.getContent());
				WxMpXmlOutMessage outMessage = wxMpMessageRouter.route(inMessage);
				if (outMessage == null) {
					// 为null，说明路由配置有问题，需要注意
					response.getWriter().write("");
					return;
				}
				response.getWriter().write(outMessage.toXml());
				return;
			}
		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}

	@PostConstruct
	public void init() {
		WechatConfig cfg = dao.find();
		if (cfg == null) {
			return;
		}
		getAccessToken(cfg);

		WxMpInMemoryConfigStorage config = new WxMpInMemoryConfigStorage();
		config.setAppId(cfg.getAppId()); // 设置微信公众号的appid
		config.setSecret(cfg.getAppSecret()); // 设置微信公众号的app corpSecret
		config.setToken(cfg.getToken()); // 设置微信公众号的token
		config.setAesKey(cfg.getAesKey());

		WxMpService wxMpService = new WxMpServiceImpl();
		wxMpService.setWxMpConfigStorage(config);

		WxMpMessageHandler handler = new WxMpMessageHandler() {
			@Override
			public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context,
					WxMpService wxMpService, WxSessionManager sessionManager) throws WxErrorException {
				WxMpXmlOutTextMessage m = WxMpXmlOutMessage.TEXT().content("测试加密消息").fromUser(wxMessage.getToUser())
						.toUser(wxMessage.getFromUser()).build();
				return m;
			}
		};

		wxMpMessageRouter = new WxMpMessageRouter(wxMpService);
		wxMpMessageRouter.rule().async(false)
				// .content("哈哈") // 拦截内容为“哈哈”的消息
				.handler(handler).end();

	}

	private String getAccessToken(WechatConfig cfg) {
		String appid = cfg.getAppId();
		String key = "_wechat_access_token:" + appid;
		accessToken = redisTemplate.opsForValue().get(key);
		if (accessToken == null || accessToken.length() == 0) {
			String secret = cfg.getAppSecret();

			String url = new StringBuilder(
					"https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=").append(appid)
							.append("&secret=").append(secret).toString();
			String res = require(url);
			
			try {
				Map<String, String> map = JSONObject.parseObject(res, HashMap.class);
				log.debug("===AccessToken请求结果:"+res);
				if(map.containsKey("access_token")) {
					accessToken = map.get("access_token");
					redisTemplate.opsForValue().set(key, accessToken);
					redisTemplate.expire(key, 1500, TimeUnit.SECONDS);
					log.debug("=========token:" + accessToken);
					return accessToken;
				}
				return null;
			} catch (Exception e) {
				e.printStackTrace();
			}
		}

		return accessToken;

	}

	public void setRedisTemplate(StringRedisTemplate redisTemplate) {
		this.redisTemplate = redisTemplate;
	}

	private String require(String url, String body) {

		RequestBody b = RequestBody.create(MediaType.parse("application/json"), body);
		Request req = new Request.Builder().url(url).post(b).build();
		try {
			Response res = client.newCall(req).execute();

			return res.body().string();
		} catch (IOException ex) {
			ex.printStackTrace();
			return null;
		}
	}

	private String require(String url) {

		Request req = new Request.Builder().url(url).build();
		try {
			Response res = client.newCall(req).execute();

			return res.body().string();
		} catch (IOException ex) {
			ex.printStackTrace();
			return null;
		}
	}
}
